package com.wangdong.wdutils.utils;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.StatFs;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.Display;


import com.wangdong.wdutils.engine.XTUtilsEngine;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class DLSystemUtil {




	/**
	 * 获取电话号(有可能为空)
	 *
	 * @param context
	 * @return
	 */
	@SuppressLint("MissingPermission")
	public static String getPhone(Context context) {
		TelephonyManager mTelephonyMgr = (TelephonyManager) context
				.getSystemService(Context.TELEPHONY_SERVICE);
		String num = mTelephonyMgr.getLine1Number();

		if (TextUtils.isEmpty(num)) {
			return "";
		} else {
			return num;
		}
	}

	/**
	 * 获取手机制造商
	 *
	 * @return
	 */
	public static String getManufacturers() {
		return android.os.Build.MANUFACTURER;
	}

	/**
	 * 获取手机品牌
	 *
	 * @return
	 */
	public static String getBrand() {
		return android.os.Build.BRAND;
	}

	/**
	 * 获取手机型号
	 *
	 * @return
	 */
	public static String getModel() {
		return android.os.Build.MODEL;
	}

	/**
	 * 获取手机操作系统
	 *
	 * @return
	 */
	public static String getOs() {
		return "Android " + android.os.Build.VERSION.INCREMENTAL;
	}

	/**
	 * 获取操作系统版本
	 *
	 * @return
	 */
	public static String getOsVersion() {
		return android.os.Build.VERSION.RELEASE;
	}

	/**
	 * 获得屏幕分辨率x(宽)
	 *
	 * @return
	 */
	public static int getScreenX(Context context) {
		return context.getResources().getDisplayMetrics().widthPixels;
	}

	/**
	 * 获得屏幕分辨率y(高)
	 *
	 * @return
	 */
	public static int getScreenY(Context context) {
		return context.getResources().getDisplayMetrics().heightPixels;
	}

	/**
	 * 是否有蓝牙
	 *
	 * @return
	 */
	public static boolean getBluetooth() {
		BluetoothAdapter bluetoothadapter = BluetoothAdapter
				.getDefaultAdapter();
		if (bluetoothadapter == null) {
			return false;
		} else {
			return true;
		}
	}



	/**
	 * 连接状态-暂时取不到
	 *
	 * @return
	 */
	public static String getConnecttype() {
		return "";
	}

	/**
	 * CPU最大频率
	 *
	 * @return
	 */
	public static String getMaxCpuFreq() {
		String result = "";
		ProcessBuilder cmd;
		try {
			String[] args = { "/system/bin/cat",
					"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" };
			cmd = new ProcessBuilder(args);
			Process process = cmd.start();
			InputStream in = process.getInputStream();
			byte[] re = new byte[24];
			while (in.read(re) != -1) {
				result = result + new String(re);
			}
			in.close();
		} catch (IOException ex) {
			ex.printStackTrace();
			result = "N/A";
		}
		return result.trim();
	}

	/**
	 * 获取CPU名字
	 */
	@SuppressWarnings("resource")
	public static String getCpuName() {
		try {
			FileReader fr = new FileReader("/proc/cpuinfo");
			BufferedReader br = new BufferedReader(fr);
			String text = br.readLine();
			String[] array = text.split(":\\s+", 2);
			for (int i = 0; i < array.length; i++) {
			}
			return array[1];
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * MAC地址
	 *
	 * @return
	 */
	public static String getMacPath(Context context) {
		WifiManager wifi = (WifiManager) context
				.getSystemService(Context.WIFI_SERVICE);

		WifiInfo info = wifi.getConnectionInfo();

		return info.getMacAddress();
	}

	/**
	 * 内存空间
	 *
	 * @return
	 */
	public static String totalRAM(Context context) {
		/*
		 * String fileName = "/proc/meminfo"; String txt; try { txt =
		 * FileUtil.read(fileName); } catch (IOException e) { Auto-generated
		 * catch block e.printStackTrace(); return 0l; } String[] lines =
		 * txt.split(StringPool.RETURN_NEW_LINE); if(lines.length < 1) return
		 * 0l; String[] line = lines[0].split(":"); if(line.length < 2) return
		 * 0l; String total = line[1]; return Long.valueOf(total);
		 */
		String str1 = "/proc/meminfo";
		String str2;
		String[] arrayOfString;
		long initial_memory = 0;
		try {
			FileReader localFileReader = new FileReader(str1);
			BufferedReader localBufferedReader = new BufferedReader(
					localFileReader, 8192);
			str2 = localBufferedReader.readLine();
			arrayOfString = str2.split("\\s+");
			for (String num : arrayOfString) {
				Log.i(str2, num + "\t");
				initial_memory = Integer.valueOf(arrayOfString[1]).intValue() * 1024;
				localBufferedReader.close();
			}
		} catch (IOException e) {

		}
		return Formatter.formatFileSize(context, initial_memory);
	}

	/**
	 * 网络制式
	 *
	 * @param context
	 * @return
	 */
	public static String getNetType(Context context) {
		TelephonyManager mTelephonyMgr = (TelephonyManager) context
				.getSystemService(Context.TELEPHONY_SERVICE);
		String result = "UNKNOWN";
		switch (mTelephonyMgr.getNetworkType()) {
			case TelephonyManager.NETWORK_TYPE_CDMA:
				result = "CDMA";
				break;
			case TelephonyManager.NETWORK_TYPE_EDGE:
				result = "EDGE";
				break;
			case TelephonyManager.NETWORK_TYPE_EVDO_0:
				result = "EVDO_0";
				break;
			case TelephonyManager.NETWORK_TYPE_EVDO_A:
				result = "EVDO_A";
				break;
			case TelephonyManager.NETWORK_TYPE_GPRS:
				result = "GPRS";
				break;
			case TelephonyManager.NETWORK_TYPE_HSDPA:
				result = "HSDPA";
				break;
			case TelephonyManager.NETWORK_TYPE_HSPA:
				result = "HSPA";
				break;
			case TelephonyManager.NETWORK_TYPE_IDEN:
				result = "IDEN";
				break;
			case TelephonyManager.NETWORK_TYPE_UMTS:
				result = "UMTS";
				break;
		}
		return result;
	}

	/**
	 * 手机制式
	 *
	 * @param context
	 * @return
	 */
	public static String phoneType(Context context) {
		TelephonyManager mTelephonyMgr = (TelephonyManager) context
				.getSystemService(Context.TELEPHONY_SERVICE);
		String type = "";
		switch (mTelephonyMgr.getPhoneType()) {
			case TelephonyManager.PHONE_TYPE_NONE:
				type = "NONE";
				break;
			case TelephonyManager.PHONE_TYPE_CDMA:
				type = "CDMA";
				break;
			case TelephonyManager.PHONE_TYPE_GSM:
				type = "GSM";
				break;
		}
		return type;
	}

	/**
	 * SD卡可用大小(MB)
	 */
	public static String availableBlock(Context context) {
		String path = Environment.getExternalStorageDirectory()
				.getAbsolutePath();
		if (path == null) {
			return "0";
		}
		android.os.StatFs statfs = new android.os.StatFs(path);
		// 获取可供程序使用的Block的数量
		long nAvailaBlock = statfs.getAvailableBlocks();
		// 获取SDCard上每个block的SIZE
		long nBlocSize = statfs.getBlockSize();

		return Formatter.formatFileSize(context, nAvailaBlock * nBlocSize);
	}

	/**
	 * 内部空间可用大小(MB)
	 */
	public static String availableRom(Context context) {
		File root = Environment.getDataDirectory();
		StatFs sf = new StatFs(root.getPath());
		long blockSize = sf.getBlockSize();
		long availCount = sf.getAvailableBlocks();

		return Formatter.formatFileSize(context, blockSize * availCount);
	}


	//===========================================================================

	/**
	 * 获取应用ID 包名
	 * @return String
	 */
	public static String getAppid(){
		return XTUtilsEngine.getInstance().getUtilsApp().getPackageName();
	}
	
	/**
	 * 获得版本号
	 * @param context Context
	 * @return String
	 */
	public static String getVersionName(Context context) {
		
		try {
			PackageManager pm = context.getPackageManager();
	        PackageInfo pinfo = pm.getPackageInfo(context.getPackageName(),
	        		PackageManager.GET_CONFIGURATIONS);
	        return pinfo.versionName;
		} catch(Exception ex) {
			ex.printStackTrace();
			return null;
		}
		
	}
	
	/**
	 * 获得版本号
	 * @param context Context
	 * @return int
	 */
	public static int getVersionCode(Context context) {
		
		try {
			PackageManager pm = context.getPackageManager();
	        PackageInfo pinfo = pm.getPackageInfo(context.getPackageName(),
	        		  PackageManager.GET_CONFIGURATIONS);
	        return pinfo.versionCode;
		} catch(Exception ex) {
			ex.printStackTrace();
			return 0;
		}
		
	}
	
	/**
	 * 获得语言信息
	 * @return String
	 */
	public static String getLanguage() {
		
		return Locale.getDefault().getLanguage() + "-" + Locale.getDefault().getCountry();
		
	}
	
	/**
	 * 获得imei
	 * @param context Context
	 * @return String
	 */
	@SuppressLint("MissingPermission")
	public static String getImei(Context context) {
		
		final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
		String imei = null;
		if (tm != null) {

			imei = tm.getDeviceId();
		}
		return imei==null?"":imei;
		
	}

	/**
	 * 获得imsi
	 * @param context Context
	 * @return String
	 */
	public static String getImsi(Context context) {
		
		TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
		@SuppressLint("MissingPermission") String imsi = tm.getSubscriberId();
		return imsi == null ? "" : imsi;
		
	}
	
	/**
	 * 获得手机类型
	 * @return String
	 */
	public static String getPhoneType() {
		
		return Build.MODEL;
	}
	
	/**
	 * 获得OS类型
	 * @return String
	 */
	public static String getOsType() {
		
		return "android_" + getSdkInfo();
		
	}
	
	/**
	 * 获得sdk level
	 * @return String
	 */
	@SuppressWarnings("deprecation")
	public static String getSdkLevel() {
		
		return Build.VERSION.SDK;
	}
	
	/**
	 * 获得sdk信息
	 * @return String
	 */
	public static String getSdkInfo() {
		
		return Build.VERSION.RELEASE;
	}
	
	/**
	 * 获得屏幕尺寸
	 * @param context Context
	 * @return String
	 */
	@SuppressWarnings("deprecation")
	public static String getScreen(Context context) {
		
		Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
		return display.getWidth() + "*" + display.getHeight();
	}
	//
	/**
	 * Pseudo-Unique ID
	 * @return String
	 */
	public static String getPseudoUniqueID(){
		String m_szDevIDShort = "35" + //we make this look like a valid IMEI
				Build.BOARD.length()%10 +
				Build.BRAND.length()%10 +
				Build.CPU_ABI.length()%10 +
				Build.DEVICE.length()%10 +
				Build.DISPLAY.length()%10 +
				Build.HOST.length()%10 +
				Build.ID.length()%10 +
				Build.MANUFACTURER.length()%10 +
				Build.MODEL.length()%10 +
				Build.PRODUCT.length()%10 +
				Build.TAGS.length()%10 +
				Build.TYPE.length()%10 +
				Build.USER.length()%10 ; //13 digits
		return m_szDevIDShort;
	}

	/**
	 * The Android ID
	 * @param resolver  ContentResolver
	 * @return String
	 */
	public static String getTheAndroidID(ContentResolver resolver){
		return Settings.Secure.getString(resolver, Settings.Secure.ANDROID_ID);
	}

	/**
	 * The WLAN MAC address string
	 * @param context Context
	 * @return String
	 */
	public static String getTheWLANMACAddressString(Context context){
		@SuppressLint("WifiManagerPotentialLeak") WifiManager wm = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
		if (wm != null) {
			return wm.getConnectionInfo().getMacAddress();
		}
		return null;
	}

	/**
	 * 获取手机唯一标示
	 * @param context Context
	 * @return String
	 */
	public static String getUdidStr(Context context ,boolean hasImei){
		String m_szLongID = hasImei?getImei(context):""
				+ getPseudoUniqueID()
				+ getTheAndroidID(context.getContentResolver())
				+ getTheWLANMACAddressString(context);

		return DLEncryptUtil.encryptMD5ToString(m_szLongID);
	}

	/**
	 * 获取application中指定的meta-data
	 * @param ctx Context
	 * @param key String
	 * @return 如果没有获取成功(没有对应值，或者异常)，则返回值为空
	 */
	public static String getAppMetaData(Context ctx, String key) {
		if (ctx == null || TextUtils.isEmpty(key)) {
			return null;
		}
		String resultData = null;
		try {
			PackageManager packageManager = ctx.getPackageManager();
			if (packageManager != null) {
				ApplicationInfo applicationInfo = packageManager.getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA);
				if (applicationInfo != null) {
					if (applicationInfo.metaData != null) {
						resultData = applicationInfo.metaData.getString(key);
					}
				}

			}
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
		}

		return resultData;
	}


	/**
	 * 获取安装App(支持7.0)的意图
	 *
	 * @param context Context
	 * @param filePath String
	 * @return Intent
	 */
	public static Intent getInstallAppIntent(Context context, String filePath) {
		//apk文件的本地路径
		File apkfile = new File(filePath);
		if (!apkfile.exists()) {
			return null;
		}
		Intent intent = new Intent(Intent.ACTION_VIEW);
		Uri contentUri = DLFileUtil.getUriForFile(context, apkfile);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
			intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
		}
		intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
		return intent;
	}

	/**
	 * 获取卸载App的意图
	 *
	 * @param packageName 包名
	 * @return 意图
	 */
	public static Intent getUninstallAppIntent(String packageName) {
		Intent intent = new Intent(Intent.ACTION_DELETE);
		intent.setData(Uri.parse("package:" + packageName));
		return intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
	}

	/**
	 * 获取打开App的意图
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return 意图
	 */
	public static Intent getLaunchAppIntent(Context context, String packageName) {
		return getIntentByPackageName(context, packageName);
	}

	/**
	 * 根据包名获取意图
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return 意图
	 */
	private static Intent getIntentByPackageName(Context context, String packageName) {
		return context.getPackageManager().getLaunchIntentForPackage(packageName);
	}

	/**
	 * 获取App信息的意图
	 *
	 * @param packageName 包名
	 * @return 意图
	 */
	public static Intent getAppInfoIntent(String packageName) {
		Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
		return intent.setData(Uri.parse("package:" + packageName));
	}

	/**
	 * 获取App信息分享的意图
	 *
	 * @param info 分享信息
	 * @return 意图
	 */
	public static Intent getShareInfoIntent(String info) {
		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.setType("text/plain");
		return intent.putExtra(Intent.EXTRA_TEXT, info);
	}

	/**
	 * 获取其他应用的Intent
	 *
	 * @param packageName 包名
	 * @param className   全类名
	 * @return 意图
	 */
	public static Intent getComponentNameIntent(String packageName, String className) {
		return getComponentNameIntent(packageName, className, null);
	}

	/**
	 * 获取其他应用的Intent
	 *
	 * @param packageName 包名
	 * @param className   全类名
	 * @param bundle      Bundle
	 * @return 意图
	 */
	public static Intent getComponentNameIntent(String packageName, String className, Bundle bundle) {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		if (bundle != null) intent.putExtras(bundle);
		ComponentName cn = new ComponentName(packageName, className);
		intent.setComponent(cn);
		return intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
	}

	/**
	 * 获取应用详情页面具体设置 intent
	 *
	 * @param mContext Context
	 * @return Intent
	 */
	public static Intent getAppDetailsSettingsIntent(Context mContext) {
		Intent localIntent = new Intent();
		localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		if (Build.VERSION.SDK_INT >= 9) {
			localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
			localIntent.setData(Uri.fromParts("package", mContext.getPackageName(), null));
		} else if (Build.VERSION.SDK_INT <= 8) {
			localIntent.setAction(Intent.ACTION_VIEW);
			localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
			localIntent.putExtra("com.android.settings.ApplicationPkgName", mContext.getPackageName());
		}
		return localIntent;
	}

	/**
	 * 获取应用详情页面具体设置 intent
	 *
	 * @param packageName 包名
	 * @return intent
	 */
	public static Intent getAppDetailsSettingsIntent(String packageName) {
		Intent localIntent = new Intent();
		localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		if (Build.VERSION.SDK_INT >= 9) {
			localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
			localIntent.setData(Uri.fromParts("package", packageName, null));
		} else if (Build.VERSION.SDK_INT <= 8) {
			localIntent.setAction(Intent.ACTION_VIEW);
			localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
			localIntent.putExtra("com.android.settings.ApplicationPkgName", packageName);
		}
		return localIntent;
	}

	/**
	 * 安装App(支持7.0)
	 *
	 * @param context  上下文
	 * @param filePath 文件路径
	 */
	public static void installApp(Context context, String filePath) {
		context.startActivity(getInstallAppIntent(context, filePath));
	}

	/**
	 * 安装App（支持7.0）
	 *
	 * @param context 上下文
	 * @param file    文件
	 */
	public static void installApp(Context context, File file) {
		if (!DLFileUtil.isFileExist(file.getAbsolutePath())) return;
		installApp(context, file.getAbsolutePath());
	}

	/**
	 * 安装App（支持7.0）
	 *
	 * @param activity    activity
	 * @param filePath    文件路径
	 * @param requestCode 请求值
	 */
	public static void installApp(Activity activity, String filePath, int requestCode) {
		activity.startActivityForResult(getInstallAppIntent(activity, filePath), requestCode);
	}

	/**
	 * 安装App(支持7.0)
	 *
	 * @param activity    activity
	 * @param file        文件
	 * @param requestCode 请求值
	 */
	public static void installApp(Activity activity, File file, int requestCode) {
		if (!DLFileUtil.isFileExist(file.getAbsolutePath())) return;
		installApp(activity, file.getAbsolutePath(), requestCode);
	}

	/**
	 * 静默安装App
	 * <p>非root需添加权限 {@code <uses-permission android:name="android.permission.INSTALL_PACKAGES" />}</p>
	 *
	 * @param context  上下文
	 * @param filePath 文件路径
	 * @return {@code true}: 安装成功<br>{@code false}: 安装失败
	 */
	public static boolean installAppSilent(Context context, String filePath) {
		File file = DLFileUtil.getFileByPath(filePath);
		if (!DLFileUtil.isFileExist(file.getAbsolutePath())) return false;
		String command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install " + filePath;
		DLShellUtil.CommandResult commandResult = DLShellUtil.execCmd(command, !isSystemApp(context), true);
		return commandResult.successMsg != null && commandResult.successMsg.toLowerCase().contains("success");
	}

	/**
	 * 判断App是否是系统应用
	 *
	 * @param context 上下文
	 * @return {@code true}: 是<br>{@code false}: 否
	 */
	public static boolean isSystemApp(Context context) {
		return isSystemApp(context, context.getPackageName());
	}

	/**
	 * 判断App是否是系统应用
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return {@code true}: 是<br>{@code false}: 否
	 */
	public static boolean isSystemApp(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return false;
		try {
			PackageManager pm = context.getPackageManager();
			ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
			return ai != null && (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 卸载App
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 */
	public static void uninstallApp(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return;
		context.startActivity(getUninstallAppIntent(packageName));
	}

	/**
	 * 卸载App
	 *
	 * @param activity    activity
	 * @param packageName 包名
	 * @param requestCode 请求值
	 */
	public static void uninstallApp(Activity activity, String packageName, int requestCode) {
		if (DLStringUtil.isEmpty(packageName)) return;
		activity.startActivityForResult(getUninstallAppIntent(packageName), requestCode);
	}

	/**
	 * 静默卸载App
	 * <p>非root需添加权限 {@code <uses-permission android:name="android.permission.DELETE_PACKAGES" />}</p>
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @param isKeepData  是否保留数据
	 * @return {@code true}: 卸载成功<br>{@code false}: 卸载成功
	 */
	public static boolean uninstallAppSilent(Context context, String packageName, boolean isKeepData) {
		if (DLStringUtil.isEmpty(packageName)) return false;
		String command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib pm uninstall " + (isKeepData ? "-k " : "") + packageName;
		DLShellUtil.CommandResult commandResult = DLShellUtil.execCmd(command, !isSystemApp(context), true);
		return commandResult.successMsg != null && commandResult.successMsg.toLowerCase().contains("success");
	}

	/**
	 * 判断App是否有root权限
	 *
	 * @return {@code true}: 是<br>{@code false}: 否
	 */
	public static boolean isAppRoot() {
		DLShellUtil.CommandResult result = DLShellUtil.execCmd("echo root", true);
		if (result.result == 0) {
			return true;
		}
		if (result.errorMsg != null) {
			DLLogUtil.e("isAppRoot", result.errorMsg);
		}
		return false;
	}

	/**
	 * 打开App
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 */
	public static void launchApp(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return;
		context.startActivity(getLaunchAppIntent(context, packageName));
	}

	/**
	 * 打开App
	 *
	 * @param activity    activity
	 * @param packageName 包名
	 * @param requestCode 请求值
	 */
	public static void launchApp(Activity activity, String packageName, int requestCode) {
		if (DLStringUtil.isEmpty(packageName)) return;
		activity.startActivityForResult(getLaunchAppIntent(activity, packageName), requestCode);
	}

	/**
	 * 获取App包名
	 *
	 * @param context 上下文
	 * @return App包名
	 */
	public static String getAppPackageName(Context context) {
		return context.getPackageName();
	}

	/**
	 * 获取App具体设置
	 *
	 * @param context 上下文
	 */
	public static void getAppDetailsSettings(Context context) {
		getAppDetailsSettings(context, context.getPackageName());
	}

	/**
	 * 获取App具体设置
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 */
	public static void getAppDetailsSettings(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return;
		context.startActivity(getAppDetailsSettingsIntent(packageName));
	}

	/**
	 * 获取App名称
	 *
	 * @param context 上下文
	 * @return App名称
	 */
	public static String getAppName(Context context) {
		return getAppName(context, context.getPackageName());
	}

	/**
	 * 获取App名称
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return App名称
	 */
	public static String getAppName(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return null;
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(packageName, 0);
			return pi == null ? null : pi.applicationInfo.loadLabel(pm).toString();
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取App图标
	 *
	 * @param context 上下文
	 * @return App图标
	 */
	public static Drawable getAppIcon(Context context) {
		return getAppIcon(context, context.getPackageName());
	}

	/**
	 * 获取App图标
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return App图标
	 */
	public static Drawable getAppIcon(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return null;
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(packageName, 0);
			return pi == null ? null : pi.applicationInfo.loadIcon(pm);
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取App路径
	 *
	 * @param context 上下文
	 * @return App路径
	 */
	public static String getAppPath(Context context) {
		return getAppPath(context, context.getPackageName());
	}

	/**
	 * 获取App路径
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return App路径
	 */
	public static String getAppPath(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return null;
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(packageName, 0);
			return pi == null ? null : pi.applicationInfo.sourceDir;
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取App版本号
	 *
	 * @param context 上下文
	 * @return App版本号
	 */
	public static String getAppVersionName(Context context) {
		return getAppVersionName(context, context.getPackageName());
	}

	/**
	 * 获取App版本号
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return App版本号
	 */
	public static String getAppVersionName(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return null;
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(packageName, 0);
			return pi == null ? null : pi.versionName;
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取App版本码
	 *
	 * @param context 上下文
	 * @return App版本码
	 */
	public static int getAppVersionCode(Context context) {
		return getAppVersionCode(context, context.getPackageName());
	}

	/**
	 * 获取App版本码
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return App版本码
	 */
	public static int getAppVersionCode(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return -1;
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(packageName, 0);
			return pi == null ? -1 : pi.versionCode;
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return -1;
		}
	}

	/**
	 * 判断App是否是Debug版本
	 *
	 * @param context 上下文
	 * @return {@code true}: 是<br>{@code false}: 否
	 */
	public static boolean isAppDebug(Context context) {
		return isAppDebug(context, context.getPackageName());
	}

	/**
	 * 判断App是否是Debug版本
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return {@code true}: 是<br>{@code false}: 否
	 */
	public static boolean isAppDebug(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return false;
		try {
			PackageManager pm = context.getPackageManager();
			ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
			return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 获取App签名
	 *
	 * @param context 上下文
	 * @return App签名
	 */
	public static Signature[] getAppSignature(Context context) {
		return getAppSignature(context, context.getPackageName());
	}

	/**
	 * 获取App签名
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return App签名
	 */
	public static Signature[] getAppSignature(Context context, String packageName) {
		if (DLStringUtil.isEmpty(packageName)) return null;
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
			return pi == null ? null : pi.signatures;
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取应用签名的的SHA1值
	 * <p>可据此判断高德，百度地图key是否正确</p>
	 *
	 * @param context 上下文
	 * @return 应用签名的SHA1字符串, 比如：53:FD:54:DC:19:0F:11:AC:B5:22:9E:F1:1A:68:88:1B:8B:E8:54:42
	 */
	public static String getAppSignatureSHA1(Context context) {
		return getAppSignatureSHA1(context, context.getPackageName());
	}

	/**
	 * 获取应用签名的的SHA1值
	 * <p>可据此判断高德，百度地图key是否正确</p>
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return 应用签名的SHA1字符串, 比如：53:FD:54:DC:19:0F:11:AC:B5:22:9E:F1:1A:68:88:1B:8B:E8:54:42
	 */
	public static String getAppSignatureSHA1(Context context, String packageName) {
		Signature[] signature = getAppSignature(context, packageName);
		if (signature == null) return null;
		return DLEncryptUtil.encryptSHA1ToString(signature[0].toByteArray()).
				replaceAll("(?<=[0-9A-F]{2})[0-9A-F]{2}", ":$0");
	}

	/**
	 * 判断App是否处于前台
	 *
	 * @param context 上下文
	 * @return {@code true}: 是<br>{@code false}: 否
	 */
	public static boolean isAppForeground(Context context) {
		ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		List<ActivityManager.RunningAppProcessInfo> infos = manager.getRunningAppProcesses();
		if (infos == null || infos.size() == 0) return false;
		for (ActivityManager.RunningAppProcessInfo info : infos) {
			if (info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
				return info.processName.equals(context.getPackageName());
			}
		}
		return false;
	}

	/**
	 * 判断App是否处于前台
	 * <p>当不是查看当前App，且SDK大于21时，
	 * 需添加权限 {@code <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>}</p>
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return {@code true}: 是<br>{@code false}: 否
	 */
	public static boolean isAppForeground(Context context, String packageName) {
		return !DLStringUtil.isEmpty(packageName) && packageName.equals(DLProcessUtil.getForegroundProcessName(context));
	}
	//----------------------------------------------------------------------------------------------------------------

	/**
	 * 判断App是否安装
	 *
	 * @param context     上下文
	 * @param packageName 包名
	 * @return {@code true}: 已安装<br>{@code false}: 未安装
	 */
	public static boolean isInstallApp(Context context, String packageName) {
		return !DLStringUtil.isEmpty(packageName) && getLaunchAppIntent(context, packageName) != null;
	}

	/**
	 * 安装APK
	 *
	 * @param context Context
	 * @param APK_PATH String
	 */
	public static void InstallAPK(Context context, String APK_PATH) {//提示安装APK
		Intent i = new Intent(Intent.ACTION_VIEW);
		i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		i.setDataAndType(Uri.parse("file://" + APK_PATH), "application/vnd.android.package-archive");
		context.startActivity(i);
	}

	/**
	 * 获取当前App信息
	 * <p>AppInfo（名称，图标，包名，版本号，版本Code，是否安装在SD卡，是否是用户程序）</p>
	 *
	 * @param context 上下文
	 * @return 当前应用的AppInfo
	 */
	public static AppInfo getAppInfo(Context context) {
		PackageManager pm = context.getPackageManager();
		PackageInfo pi = null;
		try {
			pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0);
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
		}
		return pi != null ? getBean(pm, pi) : null;
	}

	/**
	 * 得到AppInfo的Bean
	 *
	 * @param pm 包的管理
	 * @param pi 包的信息
	 * @return AppInfo类
	 */
	private static AppInfo getBean(PackageManager pm, PackageInfo pi) {
		ApplicationInfo ai = pi.applicationInfo;
		String name = ai.loadLabel(pm).toString();
		Drawable icon = ai.loadIcon(pm);
		String packageName = pi.packageName;
		String packagePath = ai.sourceDir;
		String versionName = pi.versionName;
		int versionCode = pi.versionCode;
		boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM;
		boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM;
		return new AppInfo(name, icon, packageName, packagePath, versionName, versionCode, isSD, isUser);
	}

	/**
	 * 获取所有已安装App信息
	 * <p>{@link #getBean(PackageManager, PackageInfo)}（名称，图标，包名，包路径，版本号，版本Code，是否安装在SD卡，是否是用户程序）</p>
	 * <p>依赖上面的getBean方法</p>
	 *
	 * @param context 上下文
	 * @return 所有已安装的AppInfo列表
	 */
	public static List<AppInfo> getAllAppsInfo(Context context) {
		List<AppInfo> list = new ArrayList<>();
		PackageManager pm = context.getPackageManager();
		// 获取系统中安装的所有软件信息
		List<PackageInfo> installedPackages = pm.getInstalledPackages(0);
		for (PackageInfo pi : installedPackages) {
			if (pi != null) {
				list.add(getBean(pm, pi));
			}
		}
		return list;
	}

	/**
	 * 判断当前App处于前台还是后台
	 * <p>需添加权限 {@code <uses-permission android:name="android.permission.GET_TASKS"/>}</p>
	 * <p>并且必须是系统应用该方法才有效</p>
	 *
	 * @param context 上下文
	 * @return {@code true}: 后台<br>{@code false}: 前台
	 */
	public static boolean isAppBackground(Context context) {
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		@SuppressWarnings("deprecation")
		List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
		if (!tasks.isEmpty()) {
			ComponentName topActivity = tasks.get(0).topActivity;
			if (!topActivity.getPackageName().equals(context.getPackageName())) {
				return true;
			}
		}
		return false;
	}


	/**
	 * 封装App信息的Bean类
	 */
	public static class AppInfo {

		private String name;
		private Drawable icon;
		private String packageName;
		private String packagePath;
		private String versionName;
		private int versionCode;
		private boolean isSD;
		private boolean isUser;

		/**
		 * @param name        名称
		 * @param icon        图标
		 * @param packageName 包名
		 * @param packagePath 包路径
		 * @param versionName 版本号
		 * @param versionCode 版本Code
		 * @param isSD        是否安装在SD卡
		 * @param isUser      是否是用户程序
		 */
		public AppInfo(String name, Drawable icon, String packageName, String packagePath,
					   String versionName, int versionCode, boolean isSD, boolean isUser) {
			this.setName(name);
			this.setIcon(icon);
			this.setPackageName(packageName);
			this.setPackagePath(packagePath);
			this.setVersionName(versionName);
			this.setVersionCode(versionCode);
			this.setSD(isSD);
			this.setUser(isUser);
		}

		public Drawable getIcon() {
			return icon;
		}

		public void setIcon(Drawable icon) {
			this.icon = icon;
		}

		public boolean isSD() {
			return isSD;
		}

		public void setSD(boolean SD) {
			isSD = SD;
		}

		public boolean isUser() {
			return isUser;
		}

		public void setUser(boolean user) {
			isUser = user;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getPackageName() {
			return packageName;
		}

		public void setPackageName(String packagName) {
			this.packageName = packagName;
		}

		public String getPackagePath() {
			return packagePath;
		}

		public void setPackagePath(String packagePath) {
			this.packagePath = packagePath;
		}

		public int getVersionCode() {
			return versionCode;
		}

		public void setVersionCode(int versionCode) {
			this.versionCode = versionCode;
		}

		public String getVersionName() {
			return versionName;
		}

		public void setVersionName(String versionName) {
			this.versionName = versionName;
		}

        @Override
        public String toString() {
            return getName() + "\n"
                    + getIcon() + "\n"
                    + getPackageName() + "\n"
                    + getPackagePath() + "\n"
                    + getVersionName() + "\n"
                    + getVersionCode() + "\n"
                    + isSD() + "\n"
                    + isUser() + "\n";
        }
	}
}
